(function($) {
    /**
     * 单页固定导航
     * @param  {int} startOffset 需要修正的滚动监听高度差，在需要监听的目标上方有动态变为fixed的元素时使用
     * @param option.activeCallback: function($activeItme, eventType){
     *       //$activeItme 当前选中的项 eventType: "click" or "scroll"
     *       //console.log($activeItme.html() + " " + eventType);
     *   }
     * @return {[type]}        [description]
     */
    $.fn.fixed = function(option) {
        return this.each(function() {
            var opt = $.extend({}, {
                navItemSelector : "li",
                activeClass : "active"
            }, option || {});

            var $nav        = $(this);
            var $navItems   = $nav.find(opt.navItemSelector);
            var $fixedNav   = $("#"+$nav.attr("id")+"Clone").length ? $("#"+$nav.attr("id")+"Clone") : $nav.clone().attr("id", $nav.attr("id")+"Clone").css({"display": "none", "visibility": "hidden"}).insertAfter($nav);
            var startOffset = opt.startOffset === undefined ? $nav.outerHeight(true) : opt.startOffset;
            var n           = $navItems.length;
            var left        = opt.left || $nav.offset().left || 0;
            var top         = opt.top || 0;
            var activeIndex = 0;
            var offsets     = $navItems.map(function() {
                return $($(this).data("target")).offset().top;
            }).get();
            var maxScrollTop = offsets[n-1] - startOffset + $($navItems.eq(n-1).data("target")).height() - $nav.outerHeight();
            $navItems.on("click", function() {
                resetNav();
                $(document).scrollTop(offsets[$(this).index()] - startOffset);
                if(!$(this).hasClass(opt.activeClass)){
                    activeIndex = $(this).index();
                    $(this).addClass("active").siblings().removeClass("active");
                    if(opt.activeCallback){
                        opt.activeCallback($(this),"click");
                    }
                }
                return false;
            });

            function resetNav(){
                $navItems   = $nav.find(opt.navItemSelector);
                $fixedNav   = $("#"+$nav.attr("id")+"Clone").length ? $("#"+$nav.attr("id")+"Clone") : $nav.clone().attr("id", $nav.attr("id")+"Clone").css({"display": "none", "visibility": "hidden"}).insertAfter($nav);
                startOffset = opt.startOffset === undefined ? $nav.outerHeight(true) : opt.startOffset;
                n           = $navItems.length;
                left        = opt.left || $nav.offset().left || 0;
                top         = opt.top || 0;
                offsets     = $navItems.map(function() {
                    return $($(this).data("target")).offset().top;
                }).get();
                maxScrollTop = offsets[n-1] - startOffset + $($navItems.eq(n-1).data("target")).height() - $nav.outerHeight();
            }

            $(window).on("scroll", typeof throttle === "function" ? throttle(scrollHandler, 100) : scrollHandler);
            $(window).on("resize", typeof throttle === "function" ? throttle(resizeHandler, 100) : resizeHandler);

            function scrollHandler() {
                resetNav();
                var scrolltop = $(document).scrollTop();
                if (scrolltop >= offsets[0] - startOffset && scrolltop < maxScrollTop) {
                    setNavPosition();
                    var new_index = 0;
                    $.each(offsets, function(i, v) {
                        if (scrolltop >= v - startOffset - 1) {
                            $navItems.removeClass(opt.activeClass).eq(i).addClass(opt.activeClass);
                            new_index = i;
                        }
                    });

                    if(opt.activeCallback&&activeIndex != new_index){
                        activeIndex = new_index;
                        opt.activeCallback($navItems.eq(activeIndex),"scroll");
                    }
                } else {
                    restore();
                }
            }

            function resizeHandler() {
                resetNav();
                if ($nav.hasClass("fixed")) {
                    left = opt.left || $fixedNav.css("visibility", "visible").offset().left || 0;
                    $fixedNav.css("visibility", "hidden");
                    setNavPosition();
                } else {
                    left = opt.left || $nav.offset().left || 0;
                }
            }

            function setNavPosition() {
                $nav.addClass("fixed").css({
                    "z-index": 999,
                    "left": left,
                    "top": top
                });
                $fixedNav.css({"display": "block"});
            }

            function restore() {
                $fixedNav.css({"display": "none"});
                $nav.removeClass("fixed").removeAttr("style");
                if(!$navItems.eq(0).hasClass(opt.activeClass)){
                    $navItems.removeClass(opt.activeClass).eq(0).addClass(opt.activeClass);
                    if(opt.activeCallback&&activeIndex != 0){
                        opt.activeCallback($navItems.eq(0),"scroll");
                    }
                    activeIndex = 0;
                }
            }

            scrollHandler(); // 部分浏览器有记忆机制，故页面加载时先执行一次方法
        });
    };
})(jQuery);
